package com.zijidelu.luframework.plugins.tomlock.core.handler.impl;

import com.zijidelu.luframework.plugins.tomlock.core.data.MethodParams;
import com.zijidelu.luframework.plugins.tomlock.core.data.TomLockMethodData;
import com.zijidelu.luframework.plugins.tomlock.core.data.TomLockResult;
import com.zijidelu.luframework.plugins.tomlock.core.handler.CalcMethodLockHandler;
import com.zijidelu.luframework.plugins.tomlock.core.utils.TomLockSpELUtil;
import com.zijidelu.luframework.plugins.tomlock.core.utils.TomLockUtil;
import com.zijidelu.luframework.plugins.tomlock.redisson.RedissonLockExecutor;
import lombok.RequiredArgsConstructor;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Stream;

/**
 * 处理方法模式处理器实现类。
 *
 * @author ZIJIDELU
 * @datetime 2025/4/13 19:11
 */
@Component
@RequiredArgsConstructor
public class CalcMethodLockHandlerImpl implements CalcMethodLockHandler {
    private final RedissonLockExecutor redissonLockExecutor;

    @Override
    public <T> T run(TomLockMethodData tomLockData, Supplier<T> supplier) {
        tomLockData.validParams();

        final List<Object> objects = calcMethodParamList(tomLockData);

        // 计算唯一KEY
        final String uniqueKey = TomLockUtil.calcDistributedLockKey(objects);

        final TomLockResult tomLockResult = TomLockResult.builder()
                .resultList(Stream.of(TomLockResult.LockResult.builder()
                        .module(tomLockData.getModule())
                        .business(tomLockData.getBusiness())
                        .uniqueKey(uniqueKey)
                        .build()).toList())
                .build();

        return redissonLockExecutor.calcLockRun(tomLockData, tomLockResult, supplier);
    }

    /**
     * 计算方法参数列表。
     *
     * @param tomLockData tomLockData
     * @return 方法参数列表
     */
    private List<Object> calcMethodParamList(TomLockMethodData tomLockData) {
        // SpEL表达式为空，直接返回方法参数列表
        if (tomLockData.getParamExpression().length == 0) {
            return tomLockData.getMethodParamsList().stream()
                    .map(MethodParams::getParamValue)
                    .toList();
        }

        // 构建SpEL表达式解析器
        final ExpressionParser spelExpressionParser = new SpelExpressionParser();

        // 初始化SpEL表达式上下文
        final StandardEvaluationContext standardEvaluationContext = TomLockSpELUtil.initEvaluationContext(tomLockData.getMethodParamsList());

        // 计算方法参数列表
        return TomLockSpELUtil.calcMethodParamList(tomLockData.getParamExpression(), spelExpressionParser, standardEvaluationContext);
    }

}